﻿using System;
using System.Collections.Specialized;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;

namespace API.Cryptsy
{
    public partial class Cryptsy
    {
		//set in the constructor from the  
        private readonly string _get_url = "http://pubapi.cryptsy.com/api.php";
        private readonly string _post_url = "https://api.cryptsy.com/api";

		//set by the privateley property
        private HMACSHA512 _hmac;

        //keep a serializer in memory
        private readonly JavaScriptSerializer _jsonSerializer = new JavaScriptSerializer();

        internal string API_GET_Query(string method, NameValueCollection args, int maxTryCount = 3)
        {
            if (maxTryCount < 1)
                throw new ArgumentOutOfRangeException("maxTryCount must be at least one");

            args["method"] = method;

            string queryString = ToQueryString(args);

            while (maxTryCount > 0)
            {
                try
                {
                    using (WebClient wc = new WebClient())
                        return wc.DownloadString(_get_url + "?" + queryString);
                }
                catch (Exception ex)
                {
                    if (--maxTryCount == 0)
                        throw ex;
                }
            }
            throw new ArgumentOutOfRangeException("maxTryCount must be at least one");
        }

        internal string API_POST_Query(string method, NameValueCollection args, int maxTryCount = 3)
        {
            if (string.IsNullOrEmpty(PublicKey) || string.IsNullOrEmpty(PrivateKey))
                throw new ArgumentException("Please set public and private key using the static properties");
            if (maxTryCount < 1)
                throw new ArgumentOutOfRangeException("maxTryCount must be at least one");

            args["method"] = method;
            args["nonce"] = Environment.TickCount.ToString();

            string queryString = ToQueryString(args);

            while (maxTryCount > 0)
            {
                try
                {
                    using (WebClient wc = new WebClient())
                    {
                        wc.Headers.Add(HttpRequestHeader.ContentType, "application/x-www-form-urlencoded");
                        wc.Headers.Add("Key", PublicKey);
                        wc.Headers.Add("Sign", GetMethodSignature(queryString));

                        return wc.UploadString(_post_url, queryString);
                    }
                }
                catch (Exception ex)
                {
                    if (--maxTryCount == 0)
                        throw ex;
                }
            }
            throw new ArgumentOutOfRangeException("maxTryCount must be at least one");
        }

        private static string ToQueryString(NameValueCollection nvc)
        {
            var array = (from key in nvc.AllKeys
                         from value in nvc.GetValues(key)
                         select string.Format("{0}={1}", HttpUtility.UrlEncode(key), HttpUtility.UrlEncode(value)))
                .ToArray();
            return string.Join("&", array);
        }

        private string GetMethodSignature(string queryString)
        {
            byte[] data = Encoding.UTF8.GetBytes(queryString);
            byte[] hash = _hmac.ComputeHash(data);

            return BitConverter.ToString(hash).Replace("-", "").ToLower();
        }
    }
}
